package main

import "fmt"

/**
结构体在实例化时可以直接对成员变量进行初始化。初始化有两种形式：一种是字段“键值对”形式及多个值的列表形式。键值对形式的初始化适合选择性填充字段较多的结构体；
多个值的列表形式适合填充字段较少的结构体。

使用“键值对”初始化结构体

结构体可以使用“键值对”（Key value pair）初始化字段，每个“键”（Key）对应结构体中的一个字段。键的“值”（Value）对应字段需要初始化的值。

键值对的填充是可选的，不需要初始化的字段可以不填入初始化列表中。

结构体实例化后字段的默认值是字段类型的默认值，例如：数值为 0，字符串为空字符串，布尔为 false，指针为 nil 等。

*/
func main() {
	relation := &People{
		name: "爷爷",
		child: &People{
			name: "爸爸",
			child: &People{
				name: "我",
			},
		},
	}
	fmt.Println(relation)

	addr := Address{
		"四川",
		"成都",
		610000,
		"0",
	}
	fmt.Println(addr)

	fmt.Println("匿名结构体.......")

	ins := struct {
		name string
		age  int
	}{
		"张三",
		12,
	}
	fmt.Println(ins)

	// 实例化一个匿名结构体
	msg := &struct { // 定义部分
		id   int
		data string
	}{ // 值初始化部分
		1024,
		"hello",
	}
	printMsgType(msg)
}

/**
初始化匿名结构体

匿名结构体没有类型名称，无须通过 type 关键字定义就可以直接使用。

匿名结构体定义格式和初始化写法

匿名结构体的初始化写法由结构体定义和键值对初始化两部分组成。结构体定义时没有结构体类型名，只有字段和类型定义。键值对初始化部分由可选的多个键值对组成

	ins := struct {
		// 匿名结构体字段定义
		字段1 字段类型1
		字段2 字段类型2
		…
	}{
		// 字段值初始化
		初始化字段1: 字段1的值,
		初始化字段2: 字段2的值,
		…
	}

下面是对各个部分的说明：

	字段1、字段2……：结构体定义的字段名。
	初始化字段1、初始化字段2……：结构体初始化时的字段名，可选择性地对字段初始化。
	字段类型1、字段类型2……：结构体定义字段的类型。
	字段1 的值、字段2 的值……：结构体初始化字段的初始值。

键值对初始化部分是可选的，不初始化成员时，匿名结构体的格式变为：

	ins := struct {
		字段1字段类型1
		字段2字段类型2
		…
	}

打印消息类型, 传入匿名结构体
*/
func printMsgType(msg *struct {
	id   int
	data string
}) {
	// 使用动词%T打印msg的类型
	fmt.Printf("%T\n", msg)
}

/**
使用多个值的列表初始化结构体

Go语言可以在“键值对”初始化的基础上忽略“键”。也就是说，可以使用多个值的列表初始化结构体的字段。

多个值列表初始化结构体的书写格式

多个值使用逗号分隔初始化结构体，例如：

	ins := 结构体类型名{
		字段1的值,
		字段2的值,
		…
	}

使用这种格式初始化时，需要注意：

	必须初始化结构体的所有字段。
	每一个初始值的填充顺序必须与字段在结构体中的声明顺序一致。
	键值对与值列表的初始化形式不能混用。
*/
type Address struct {
	Province    string
	City        string
	ZipCode     int
	PhoneNumber string
}

/**
键值对初始化结构体的书写格式

键值对初始化的格式如下：

	ins := 结构体类型名{
		字段1: 字段1的值,
		字段2: 字段2的值,
	}

下面是对各个部分的说明：

	结构体类型：定义结构体时的类型名称。
	字段1、字段2：结构体的成员字段名。结构体类型名的字段初始化列表中，字段名只能出现一次。
	字段1 的值、字段2 的值：结构体成员字段的初始值

键值之间以:分隔；键值对之间以,分隔
*/
type People struct {
	name  string
	child *People
}
